package com.leslie.hhcommunity.service.impl;

import com.leslie.hhcommunity.dao.elasticsearch.DiscussPostRepository;
import com.leslie.hhcommunity.entity.DiscussPost;
import com.leslie.hhcommunity.service.ElasticSearchService;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author
 * @PackageName:com.leslie.hhcommunity.service.impl
 * @ClassnName:ElasticSearchServiceImpl
 * @Description:
 * @Date 2022/1/10  14:03
 */
@Service
public class ElasticSearchServiceImpl implements ElasticSearchService {

	@Autowired
	DiscussPostRepository discussRepository;

	@Autowired
	ElasticsearchTemplate elasticTemplate;


	/**
	 * 保存
	 * @param post
	 */
	@Override
	public void saveDiscussPost(DiscussPost post) {
		discussRepository.save(post);
	}

	/**
	 * 删除
	 * @param id
	 */
	@Override
	public void deleteDiscussPost(int id) {
		discussRepository.deleteById(id);
	}

	/**
	 * 搜索
	 * @param keyword
	 * @param current
	 * @param limit
	 * @return
	 */
	@Override
	public Page<DiscussPost> searchDiscussPost(String keyword, int current, int limit) {
		SearchQuery searchQuery = new NativeSearchQueryBuilder()
				//构造多字段查询
				.withQuery(QueryBuilders.multiMatchQuery(keyword, "title", "content"))
				//设置排序字段为type,score,createTime 倒序
				.withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC))
				.withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC))
				.withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))
				//分页
				.withPageable(PageRequest.of(current, limit))
				//设置高亮的前标签和后标签
				.withHighlightFields(
						new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"),
						new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>")
				).build();

		// elasticsearchTemplate得到结果交给SearchResultMapper处理之后再返回
		return elasticTemplate.queryForPage(searchQuery, DiscussPost.class, new SearchResultMapper() {
			@Override
			public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> aClass, Pageable pageable) {
				// 得到所有命中数据
				SearchHits hits = response.getHits();
				if (hits.getTotalHits() <= 0) {
					return null;
				}

				List<DiscussPost> list = new ArrayList<>();
				for (SearchHit hit : hits) {
					DiscussPost post = new DiscussPost();
					// 得到每个被遍历数据的信息，然后设置post
					String id = hit.getSourceAsMap().get("id").toString();
					post.setId(Integer.valueOf(id));

					String userId = hit.getSourceAsMap().get("userId").toString();
					post.setUserId(Integer.valueOf(userId));

					String title = hit.getSourceAsMap().get("title").toString();
					post.setTitle(title);

					String content = hit.getSourceAsMap().get("content").toString();
					post.setContent(content);

					String status = hit.getSourceAsMap().get("status").toString();
					post.setStatus(Integer.valueOf(status));

					String createTime = hit.getSourceAsMap().get("createTime").toString();
					post.setCreateTime(new Date(Long.valueOf(createTime)));

					String commentCount = hit.getSourceAsMap().get("commentCount").toString();
					post.setCommentCount(Integer.valueOf(commentCount));

					// 处理高亮显示的结果
					// 得到title字段的高亮数据
					HighlightField titleField = hit.getHighlightFields().get("title");
					if (titleField != null) {
						// 只取第一个高亮
						post.setTitle(titleField.getFragments()[0].toString());
					}
					// 处理高亮显示的结果
					HighlightField contentField = hit.getHighlightFields().get("content");
					if (contentField != null) {
						post.setContent(contentField.getFragments()[0].toString());
					}

					list.add(post);
				}
				// 对返回数据进行初始化，传入list，其他参数固定对结果进行返回
				return new AggregatedPageImpl(list, pageable,
						hits.getTotalHits(), response.getAggregations(), response.getScrollId(), hits.getMaxScore());
			}
		});
	}
}
